package io.terminus.paas.profiler.service.impl

import com.alibaba.dubbo.common.Constants
import com.alibaba.dubbo.common.URL
import io.terminus.paas.profiler.AbstractProfilerService
import io.terminus.paas.profiler.model.Route
import io.terminus.paas.profiler.service.RouteService
import io.terminus.paas.profiler.utils.ConvertUtil
import io.terminus.paas.profiler.utils.ProfilerConstants
import io.terminus.paas.profiler.model.Permission
import io.terminus.paas.profiler.service.PermissionService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.text.ParseException

/**
 * Created by gengrong on 16/3/25.
 */
@Service
class PermissionServiceImpl @Autowired constructor(
        val routeService: RouteService
) : PermissionService, AbstractProfilerService() {

    override fun savePermission(registryAddress: String, serviceId: String, allow: String, denial: String) {
        val routeUrls = getRouteUrls(registryAddress)[serviceId];
        val routeUrl = routeUrls?.entries?.firstOrNull {
            it.value.parameters["name"] == (serviceId + ProfilerConstants.PERMISSION_ALLOW_NAME)
        }
        var rule: String = "";
        if (allow.isNotEmpty()) {
            rule = ProfilerConstants.CONSUMER_APPLICATION + " != " + allow;
        }
        if (denial.isNotEmpty()) {
            if (rule.isEmpty()) {
                rule = ProfilerConstants.CONSUMER_APPLICATION + " = " + denial;
            } else {
                rule += " & ";
                rule += ProfilerConstants.CONSUMER_APPLICATION + " = " + denial;
            }
        }
        rule += " => false";
        val route = Route();
        route.priority = 100
        route.service = serviceId
        route.name = serviceId + ProfilerConstants.PERMISSION_ALLOW_NAME
        route.enabled = true
        route.setRuleStr(rule);
        if (routeUrl != null) {
            route.id = routeUrl.key;
            routeService.updateRoute(registryAddress, route);
        } else {
            routeService.createRoute(registryAddress, route)
        }
    }

    override fun findByServiceId(registryAddress: String, serviceId: String): Permission {
        val ret = Permission()
        val routeUrls = getRouteUrls(registryAddress)[serviceId];
        val permissionUrl = routeUrls?.values?.firstOrNull {
            it.parameters["name"] == (serviceId + ProfilerConstants.PERMISSION_ALLOW_NAME)
        }
        permissionUrl?.let {
            parsePermissionByUrl(it)[ProfilerConstants.CONSUMER_APPLICATION]?.let { condition ->
                ret.allowAppNameList = condition.unmatches
                ret.denialAppNameList = condition.matches
            }
        }
        return ret
    }

    // TODO 丑陋无比的处理方式
    fun parsePermissionByUrl(url: URL): Map<String, ConvertUtil.MatchPair> {
        val rule = ConvertUtil.decode(url.parameters[Constants.RULE_KEY])!!;
        val matcher = ProfilerConstants.CONDITION_SEPERATOR.matcher(rule)
        if (!matcher.matches()) throw ParseException("condition seperator => not found!", 0)
        val whenRule = matcher.group(1)
        //            val thenRule = matcher.group(2)
        val ruleMap = ConvertUtil.parseRule(whenRule);
        return ruleMap;
    }

}